package com.whfc.safety.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.whfc.base.param.AppFileExportParam;
import com.whfc.base.service.AppExportService;
import com.whfc.base.service.WarnConfigService;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.AppWarnModuleType;
import com.whfc.common.enums.AppWarnMsgChannel;
import com.whfc.common.exception.BizException;
import com.whfc.common.file.FileHandler;
import com.whfc.common.file.FilePathConfig;
import com.whfc.common.file.properties.FileExpirationRules;
import com.whfc.common.result.PageVO;
import com.whfc.common.result.PageVOUtil;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.*;
import com.whfc.entity.dto.msg.AppMsgToUserDTO;
import com.whfc.entity.dto.msg.PushMsgDTO;
import com.whfc.entity.dto.statistics.CheckDetailDTO;
import com.whfc.entity.dto.statistics.CheckStatisticsDTO;
import com.whfc.entity.dto.statistics.StatisticsProgressDTO;
import com.whfc.entity.dto.statistics.StatisticsProgressUnitDTO;
import com.whfc.entity.param.check.CheckSearchParam;
import com.whfc.fuum.service.SysDeptService;
import com.whfc.safety.dao.*;
import com.whfc.safety.dto.*;
import com.whfc.safety.entity.*;
import com.whfc.safety.enums.*;
import com.whfc.safety.param.SafetyCheckListParam;
import com.whfc.safety.param.SafetyCheckLogParam;
import com.whfc.safety.param.SafetyCheckParam;
import com.whfc.safety.param.SafetyCheckUserParam;
import com.whfc.safety.service.SafetyCheckService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClasssName SafetyCheckServiceImpl
 * @Description 安全管理问题上报接口实现类
 * @Author hw
 * @Date 2020/8/5 10:29
 * @Version 1.0
 */
@DubboService(interfaceClass = SafetyCheckService.class, version = "1.0.0", timeout = 5000)
public class SafetyCheckServiceImpl implements SafetyCheckService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SafetyCheckLogMapper safetyCheckLogMapper;
    @Autowired
    private SafetyCheckMapper safetyCheckMapper;
    @Autowired
    private SafetyCheckUserMapper safetyCheckUserMapper;
    @Autowired
    private SafetyCheckImgMapper safetyCheckImgMapper;

    @DubboReference(interfaceClass = AppExportService.class, version = "1.0.0")
    private AppExportService appExportService;

    @DubboReference(interfaceClass = SysDeptService.class, version = "1.0.0")
    private SysDeptService sysDeptService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private FilePathConfig msFilePathConfig;

    @Autowired
    private FileHandler fileHandler;

    @Autowired
    private SafetyIssueTypeMapper safetyIssueTypeMapper;

    private JSONObject pdfConfig;


    private final static String PDF_CONFIG_PATH = "pdfConfig/config.json";

    private final static String EXPORT_IMG_TEMPLATE = "<img src='%s' />";

    private final static String QUALITY_FILE_DESC = "安全问题导出";

    private final static String HTML_TEMPLATE_PATH = "pdfTemp/safetyCheckTemp.html";

    @PostConstruct
    public void info() throws IOException {
        ClassPathResource resource = new ClassPathResource(PDF_CONFIG_PATH);
        InputStream templateFileInputStream = resource.getInputStream();
        String pdfConfigStr = new String(FileUtil.readData(templateFileInputStream));
        if (StringUtils.isNotEmpty(pdfConfigStr)) {
            pdfConfig = JSONObject.parseObject(pdfConfigStr);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCheck(SafetyCheckParam safetyCheckParam) throws BizException {
        logger.info("新增问题上报信息 SafetyCheckParam：{}", safetyCheckParam.toString());
        if (UrgencyLevel.parseValue(safetyCheckParam.getUrgency()) == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "紧急程度编码不存在");
        }
        if (safetyCheckParam.getCheckUsers().stream().distinct().count() < safetyCheckParam.getCheckUsers().size()) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "安全问题上报用户信息重复");
        }
        //判断检查部位ID是否有值，没有值得情况为手动录入
        if (safetyCheckParam.getPartId() == null) {
            safetyCheckParam.setPartId(-1);
        }
        //判断问题类型ID是否有值，没有值得情况为手动录入
        if (safetyCheckParam.getIssueTypeId() == null) {
            safetyCheckParam.setIssueTypeId(-1L);
            //特殊处理当问题内别没有时数据库会返回异常需要手动存入值（手动录入）
            safetyCheckParam.setIssueTypeName("手动录入");
        }
        //判断问题明细是否有值，没有值得情况为手动录入
        if (safetyCheckParam.getIssueId() == null) {
            safetyCheckParam.setIssueId(-1L);
        }

        SafetyCheck safetyCheck = new SafetyCheck();
        //开始保存安全问题主表
        insertCheck(safetyCheckParam, safetyCheck);
        //开始保存安全问题记录相关人员和安全问题流程处理
        SafetyCheckLog checkLog = inserCheckUserAndLog(safetyCheckParam, safetyCheck);

        if(!CollectionUtils.isEmpty(safetyCheckParam.getImgUrls())) {
            for (String imgUrl : safetyCheckParam.getImgUrls()) {
                SafetyCheckImg checkImg = new SafetyCheckImg();
                checkImg.setCheckId(safetyCheck.getId());
                checkImg.setLogId(checkLog.getId());
                checkImg.setImgUrl(imgUrl);
                safetyCheckImgMapper.insertSelective(checkImg);
            }
        }
        SafetyCheckDTO safetyCheckDTO = new SafetyCheckDTO();
        BeanUtils.copyProperties(safetyCheck, safetyCheckDTO);
        safetyCheckDTO.setCheckId(safetyCheck.getId());
        generateMessage(safetyCheckDTO, safetyCheckParam.getCheckUsers());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCheckLog(SafetyCheckLogParam safetyCheckLogParam) throws BizException {
        logger.info("问题处理流程 SafetyCheckLogParam：{}", safetyCheckLogParam.toString());
        SafetyCheck check = safetyCheckMapper.selectByPrimaryKey(safetyCheckLogParam.getCheckId());
        verifyCheckLog(safetyCheckLogParam, check);
        if (!SafetyOptionType.RECTIFY.getValue().equals(safetyCheckLogParam.getOpType()) && SafetyOptionResult.QUALIFIED.getValue().equals(safetyCheckLogParam.getOpResult())) {
            //如果状态不为整改并且合格的情况下，在复查的时候安全问题状态为待核验，在核验的情况差问题安全状态为完成
            if (SafetyOptionType.REVIEW.getValue().equals(safetyCheckLogParam.getOpType())) {
                List<SafetyCheckUserDTO> dtos = safetyCheckUserMapper.selectQualityCheckUserDTOList(check.getId(), SafetyOptionType.VERIFY.getValue());
                if (dtos.isEmpty()) {
                    check.setState(SafetyCheckState.SUCCESS.getValue());
                } else {
                    check.setState(SafetyCheckState.TO_BE_VERIFIED.getValue());
                }
            } else if (SafetyOptionType.VERIFY.getValue().equals(safetyCheckLogParam.getOpType())) {
                check.setState(SafetyCheckState.SUCCESS.getValue());
            }
        } else {
            //如果状态为整改时或不合格时，在整改状态下安全问题状态改为待复查，在复查状态下不合格时状态改为待整改(复查不合格)，在审核状态下不合格时状态改为待整改(核验不合格)
            if (SafetyOptionType.RECTIFY.getValue().equals(safetyCheckLogParam.getOpType())) {
                check.setState(SafetyCheckState.TO_BE_REVIEWED.getValue());
            } else if (SafetyOptionType.REVIEW.getValue().equals(safetyCheckLogParam.getOpType())) {
                check.setState(SafetyCheckState.UNQUALIFIED_REVIEW.getValue());
            } else if (SafetyOptionType.VERIFY.getValue().equals(safetyCheckLogParam.getOpType())) {
                check.setState(SafetyCheckState.UNQUALIFIED_VERIFY.getValue());
            }
        }

        SafetyCheckLog checkLog = new SafetyCheckLog();

        BeanUtils.copyProperties(safetyCheckLogParam, checkLog);
        Date opTime = new Date();
        checkLog.setOpTime(opTime);
        if (SafetyOptionType.RECTIFY.getValue().equals(safetyCheckLogParam.getOpType())) {
            checkLog.setOpResult(null);
        }
        safetyCheckLogMapper.insertSelective(checkLog);
        if (!safetyCheckLogParam.getImgUrls().isEmpty()) {
            for (String imgUrl : safetyCheckLogParam.getImgUrls()) {
                SafetyCheckImg checkImg = new SafetyCheckImg();
                checkImg.setCheckId(check.getId());
                checkImg.setLogId(checkLog.getId());
                checkImg.setImgUrl(imgUrl);
                safetyCheckImgMapper.insertSelective(checkImg);
            }
        }
        safetyCheckMapper.updateByPrimaryKey(check);
        //发送消息
        generateMessage(safetyCheckLogParam, check, opTime);
    }

    @Override
    public void delCheck(Integer checkId) throws BizException {
        safetyCheckMapper.del(checkId);
    }

    @Override
    public SafetyCheckListDTO list(SafetyCheckListParam safetyCheckListParam) throws BizException {
        logger.info("安全问题上报列表 SafetyCheckListParam：{}", safetyCheckListParam.toString());
        Integer[] type = {SafetyCheckUserType.RECTIFIER.getValue(), SafetyCheckUserType.REVIEWER.getValue(), SafetyCheckUserType.VERIFIER.getValue()};
        List<SafetyCheckDTO> list = safetyCheckMapper.selectByDeptId(safetyCheckListParam);
        SafetyCheckListDTO safetyCheckListDTO = new SafetyCheckListDTO();
        safetyCheckListDTO.setCheckList(list);
        safetyCheckListDTO.setReportNum(safetyCheckMapper.countReport(safetyCheckListParam));
        SafetyCheckListParam allNumCheckListParam = new SafetyCheckListParam();
        BeanUtils.copyProperties(safetyCheckListParam, allNumCheckListParam);
        allNumCheckListParam.setType(null);
        safetyCheckListDTO.setAllNum(safetyCheckMapper.selectByDeptId(allNumCheckListParam).size());
        for (SafetyCheckDTO safetyCheckDTO : safetyCheckListDTO.getCheckList()) {
            safetyCheckDTO.setImgUrlList(safetyCheckImgMapper.selectByCheckId(safetyCheckDTO.getCheckId(), SafetyCheckUserType.REPORTER.getValue(), null));
            safetyCheckDTO.setRectifyImgUrlList(safetyCheckImgMapper.selectByCheckId(safetyCheckDTO.getCheckId(), SafetyCheckUserType.RECTIFIER.getValue(), null));
            safetyCheckDTO.setRectifyUserName(safetyCheckUserMapper.selectUserNamesByType(safetyCheckDTO.getCheckId(), SafetyCheckUserType.RECTIFIER.getValue()));
        }
        if (Arrays.equals(type, safetyCheckListParam.getType())) {
            return screeningCheckList(safetyCheckListParam, list, safetyCheckListDTO, true);
        }
        calculatePage(list, safetyCheckListParam, safetyCheckListDTO);
        safetyCheckListParam.setType(type);
        safetyCheckListDTO.setDisposeNum(screeningCheckList(safetyCheckListParam, safetyCheckMapper.selectByDeptId(safetyCheckListParam), new SafetyCheckListDTO(), false).getCheckList().size());
        return safetyCheckListDTO;
    }

    @Override
    public List<SafetyCheckDTO> dayLogList(SafetyCheckListParam safetyCheckListParam) throws BizException {
        List<SafetyCheckDTO> list = safetyCheckMapper.selectByDeptId(safetyCheckListParam);
        for (SafetyCheckDTO safetyCheckDTO : list) {
            safetyCheckDTO.setImgUrlList(safetyCheckImgMapper.selectByCheckId(safetyCheckDTO.getCheckId(), SafetyCheckUserType.REPORTER.getValue(), null));
            safetyCheckDTO.setRectifyImgUrlList(safetyCheckImgMapper.selectByCheckId(safetyCheckDTO.getCheckId(), SafetyCheckUserType.RECTIFIER.getValue(), null));
        }
        return list;
    }

    @Override
    public SafetyCheckDescDTO desc(Integer checkId) throws BizException {
        logger.info("安全问题上报详情 checkId：{}", checkId);
        SafetyCheckDescDTO checkDescDTO = safetyCheckMapper.selectById(checkId);
        SafetyIssueType safetyIssueType = safetyIssueTypeMapper.selectByIssueTypeId(checkDescDTO.getIssueTypeId());
        if(null == safetyIssueType){
            checkDescDTO.setIssueTypeName("其他");
        }else{
            checkDescDTO.setIssueTypeName(safetyIssueType.getName());
        }
        checkDescDTO.setImgUrlList(safetyCheckImgMapper.selectByCheckId(checkId, SafetyOptionType.REPORT.getValue(), checkDescDTO.getLogId()));
        List<SafetyCheckLogListDTO> logList = safetyCheckLogMapper.selectByCheckId(checkId);
        for (SafetyCheckLogListDTO logListDTO : logList) {
            logListDTO.setImgUrlList(safetyCheckImgMapper.selectByCheckId(checkId, logListDTO.getOpType(), logListDTO.getLogId()));
        }
        checkDescDTO.setLogList(logList);
        checkDescDTO.setUserList(safetyCheckUserMapper.selectByCheckId(checkId));
        return checkDescDTO;
    }

    @Override
    public List<SafetyCheckDescDTO> descByIds(List<Integer> safetyCheckIds) throws BizException {
        if (CollectionUtils.isEmpty(safetyCheckIds)) {
            return new ArrayList<>();
        }
        List<SafetyCheckDescDTO> checkDescDTOList = safetyCheckMapper.selectByIds(safetyCheckIds);
        checkDescDTOList.forEach(checkDescDTO->{
            SafetyIssueType safetyIssueType = safetyIssueTypeMapper.selectByIssueTypeId(checkDescDTO.getIssueTypeId());
            if(null == safetyIssueType){
                checkDescDTO.setIssueTypeName("其他");
            }else{
                checkDescDTO.setIssueTypeName(safetyIssueType.getName());
            }
        });
        List<SafetyCheckLogListDTO> logList = safetyCheckLogMapper.selectByCheckIds(safetyCheckIds);
        Map<Integer, List<SafetyCheckLogListDTO>> logMap = logList.stream().collect(Collectors.groupingBy(SafetyCheckLogListDTO::getCheckId));

        List<SafetyCheckUserDTO> userList = safetyCheckUserMapper.selectByCheckIds(safetyCheckIds);
        Map<Integer, List<SafetyCheckUserDTO>> userMap = userList.stream().collect(Collectors.groupingBy(SafetyCheckUserDTO::getCheckId));

        checkDescDTOList.forEach(s->{
            s.setLogList(logMap.get(s.getId()));
            s.setUserList(userMap.get(s.getId()));
        });
        return checkDescDTOList;
    }

    @Override
    public SafetyCheckStatisticalDTO statistical(Integer deptId, Date startTime, Date endTime, Integer channel) throws BizException {
        logger.info("安全问题上报统计分析 deptId：{},startTime:{},endTime:{},channel:{}", deptId, startTime, endTime, channel);
        SafetyCheckStatisticalDTO safetyCheckStatisticalDTO = new SafetyCheckStatisticalDTO();
        safetyCheckStatisticalDTO.setGeneral(0L);
        safetyCheckStatisticalDTO.setRectified(0L);
        safetyCheckStatisticalDTO.setReviewed(0L);
        safetyCheckStatisticalDTO.setSuccess(0L);
        safetyCheckStatisticalDTO.setUnqualified(0L);
        safetyCheckStatisticalDTO.setUrgency(0L);
        safetyCheckStatisticalDTO.setVerified(0L);
        String a ="地基与基础工程";
        List<SafetyCheckIssueStatisticalDTO> safetyCheckIssueStatisticalDTOS = safetyCheckMapper.selectIssueByCheckTime(deptId, null, startTime, endTime);
        safetyCheckIssueStatisticalDTOS.forEach(safetyCheckIssueStatisticalDTO -> {
            SafetyIssueType safetyIssueType = safetyIssueTypeMapper.selectByIssueTypeId(safetyCheckIssueStatisticalDTO.getIssueTypeId());
            if(null == safetyIssueType){
                safetyCheckIssueStatisticalDTO.setIssueName("其他");
            }else{
                safetyCheckIssueStatisticalDTO.setIssueName(safetyIssueType.getName());
            }
        });
        safetyCheckStatisticalDTO.setIssue(safetyCheckIssueStatisticalDTOS);
        safetyCheckStatisticalDTO.setPart(safetyCheckMapper.selectPartByCheckTime(deptId, null,startTime, endTime));

        // 设置一般的用户统计数
        safetyCheckStatisticalDTO.setGeneralUserList(safetyCheckMapper.selectByCheckTimeAndUrgency(deptId, UrgencyLevel.GENERAL.getValue(), startTime, endTime));
        // 设置紧急的用户统计数
        safetyCheckStatisticalDTO.setUrgencyUserList(safetyCheckMapper.selectByCheckTimeAndUrgency(deptId, UrgencyLevel.URGENCY.getValue(), startTime, endTime));


        List<Map<String, Long>> mapList = safetyCheckMapper.selectByStateAndCheckTime(deptId, null,startTime, endTime);
        for (Map<String, Long> map : mapList) {
            if (SafetyCheckState.TO_BE_RECTIFIED.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setRectified(map.get("num"));
            } else if (SafetyCheckState.TO_BE_REVIEWED.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setReviewed(map.get("num"));
            } else if (SafetyCheckState.UNQUALIFIED_VERIFY.getValue().equals(map.get("state")) || SafetyCheckState.UNQUALIFIED_REVIEW.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setUnqualified(safetyCheckStatisticalDTO.getUnqualified() + (map.get("num")));
            } else if (SafetyCheckState.TO_BE_VERIFIED.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setVerified((map.get("num")));
            } else if (SafetyCheckState.SUCCESS.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setSuccess((map.get("num")));
            }
        }
        List<Map<String, Long>> urgencyMapList = safetyCheckMapper.selectByUrgencyAndCheckTime(deptId, null, startTime, endTime);
        for (Map<String, Long> map : urgencyMapList) {
            if (UrgencyLevel.URGENCY.getValue().equals(map.get("urgency"))) {
                safetyCheckStatisticalDTO.setUrgency((map.get("num")));
            } else if (UrgencyLevel.GENERAL.getValue().equals(map.get("urgency"))) {
                safetyCheckStatisticalDTO.setGeneral((map.get("num")));
            }
        }
        List<Date> dateList = null;
        if (channel == 1) {
            dateList = DateUtil.getDayList(startTime, endTime);
        } else {
            dateList = DateUtil.getMonthListBetween(DateUtil.addMonth(startTime, -11), startTime);
        }
        List<SafetyCheckMonthStatisticalDTO> monthStatisticals = new ArrayList<>();
        for (Date date : dateList) {
            if (date.getTime() <= System.currentTimeMillis()) {
                SafetyCheckMonthStatisticalDTO monthStatisticalDTO = new SafetyCheckMonthStatisticalDTO();
                monthStatisticalDTO.setDate(date);
                monthStatisticalDTO.setNum(safetyCheckMapper.selectByCheckTime(deptId, null, date, channel));
                monthStatisticals.add(monthStatisticalDTO);
            }
        }
        safetyCheckStatisticalDTO.setMonth(monthStatisticals);
        return safetyCheckStatisticalDTO;
    }
    @Override
    public SafetyCheckStatisticalDTO statistical(Integer deptId, Integer userId,Date startTime, Date endTime, Integer channel) throws BizException {
        logger.info("安全问题上报统计分析 deptId：{},startTime:{},endTime:{},channel:{}", deptId, startTime, endTime, channel);
        SafetyCheckStatisticalDTO safetyCheckStatisticalDTO = new SafetyCheckStatisticalDTO();
        safetyCheckStatisticalDTO.setGeneral(0L);
        safetyCheckStatisticalDTO.setRectified(0L);
        safetyCheckStatisticalDTO.setReviewed(0L);
        safetyCheckStatisticalDTO.setSuccess(0L);
        safetyCheckStatisticalDTO.setUnqualified(0L);
        safetyCheckStatisticalDTO.setUrgency(0L);
        safetyCheckStatisticalDTO.setVerified(0L);
        String a ="地基与基础工程";
        List<SafetyCheckIssueStatisticalDTO> safetyCheckIssueStatisticalDTOS = safetyCheckMapper.selectIssueByCheckTime(deptId, userId, startTime, endTime);
        safetyCheckIssueStatisticalDTOS.forEach(safetyCheckIssueStatisticalDTO -> {
            SafetyIssueType safetyIssueType = safetyIssueTypeMapper.selectByIssueTypeId(safetyCheckIssueStatisticalDTO.getIssueTypeId());
            if(null == safetyIssueType){
                safetyCheckIssueStatisticalDTO.setIssueName("其他");
            }else{
                safetyCheckIssueStatisticalDTO.setIssueName(safetyIssueType.getName());
            }
        });
        safetyCheckStatisticalDTO.setIssue(safetyCheckIssueStatisticalDTOS);
        safetyCheckStatisticalDTO.setPart(safetyCheckMapper.selectPartByCheckTime(deptId, userId, startTime, endTime));

        // 设置一般的用户统计数
        safetyCheckStatisticalDTO.setGeneralUserList(safetyCheckMapper.selectByCheckTimeAndUrgency(deptId, UrgencyLevel.GENERAL.getValue(), startTime, endTime));
        // 设置紧急的用户统计数
        safetyCheckStatisticalDTO.setUrgencyUserList(safetyCheckMapper.selectByCheckTimeAndUrgency(deptId, UrgencyLevel.URGENCY.getValue(), startTime, endTime));


        List<Map<String, Long>> mapList = safetyCheckMapper.selectByStateAndCheckTime(deptId, userId, startTime, endTime);
        for (Map<String, Long> map : mapList) {
            if (SafetyCheckState.TO_BE_RECTIFIED.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setRectified(map.get("num"));
            } else if (SafetyCheckState.TO_BE_REVIEWED.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setReviewed(map.get("num"));
            } else if (SafetyCheckState.UNQUALIFIED_VERIFY.getValue().equals(map.get("state")) || SafetyCheckState.UNQUALIFIED_REVIEW.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setUnqualified(safetyCheckStatisticalDTO.getUnqualified() + (map.get("num")));
            } else if (SafetyCheckState.TO_BE_VERIFIED.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setVerified((map.get("num")));
            } else if (SafetyCheckState.SUCCESS.getValue().equals(map.get("state"))) {
                safetyCheckStatisticalDTO.setSuccess((map.get("num")));
            }
        }
        List<Map<String, Long>> urgencyMapList = safetyCheckMapper.selectByUrgencyAndCheckTime(deptId, userId, startTime, endTime);
        for (Map<String, Long> map : urgencyMapList) {
            if (UrgencyLevel.URGENCY.getValue().equals(map.get("urgency"))) {
                safetyCheckStatisticalDTO.setUrgency((map.get("num")));
            } else if (UrgencyLevel.GENERAL.getValue().equals(map.get("urgency"))) {
                safetyCheckStatisticalDTO.setGeneral((map.get("num")));
            }
        }
        List<Date> dateList = null;
        if (channel == 1) {
            dateList = DateUtil.getDayList(startTime, endTime);
        } else {
            dateList = DateUtil.getMonthListBetween(DateUtil.addMonth(startTime, -11), startTime);
        }
        List<SafetyCheckMonthStatisticalDTO> monthStatisticals = new ArrayList<>();
        for (Date date : dateList) {
            if (date.getTime() <= System.currentTimeMillis()) {
                SafetyCheckMonthStatisticalDTO monthStatisticalDTO = new SafetyCheckMonthStatisticalDTO();
                monthStatisticalDTO.setDate(date);
                monthStatisticalDTO.setNum(safetyCheckMapper.selectByCheckTime(deptId, userId, date, channel));
                monthStatisticals.add(monthStatisticalDTO);
            }
        }
        safetyCheckStatisticalDTO.setMonth(monthStatisticals);
        return safetyCheckStatisticalDTO;
    }

    @Override
    public List<Integer> getCheckIds() throws BizException {
        return safetyCheckMapper.selectCheckIdAll();
    }

    @Override
    public void updateOverdue(List<Integer> checkIds) throws BizException {
        safetyCheckMapper.updateOverdue(checkIds);
    }

    @Override
    public SafetyLogDTO safetyLog(Integer deptId, Date date) throws BizException {
        logger.info("问题日志，deptId：{},date:{}", deptId, date);
        Date startTime = DateUtil.getDateBegin(date);
        Date endTime = DateUtil.getDateEnd(date);
        List<SafetyUserNumDTO> questionList = safetyCheckMapper.selectUserNum(deptId, date);
        Integer questionNum = questionList.stream().mapToInt(SafetyUserNumDTO::getNum).sum();
        List<SafetyIssueNumDTO> issueList = safetyCheckMapper.selectIssueNum(deptId, startTime, endTime);
        SafetyLogDTO safetyLogDTO = new SafetyLogDTO();
        safetyLogDTO.setAllNum(questionNum);
        safetyLogDTO.setQuestionNum(questionNum);
        // TODO: 2021/3/22 检查未开发开发时需要修改
        safetyLogDTO.setCheckNum(0);
        safetyLogDTO.setQuestionList(questionList);
        safetyLogDTO.setIssueList(issueList);
        return safetyLogDTO;
    }


    @Override
    public void safetyExport(List<Integer> safetyIds, Integer deptId) throws BizException {

        String fileDesc = QUALITY_FILE_DESC;
        String fileName = RandomUtil.getRandomFileName();
        String suffix = safetyIds.size() > 1 ? "zip" : "pdf";
        AppFileExportParam fileExport = new AppFileExportParam();
        fileExport.setDeptId(deptId);
        fileExport.setFileName(fileName);
        fileExport.setFileFormat(suffix.toUpperCase());
        fileExport.setFileState(0);
        fileExport.setFileDesc(fileDesc);
        Integer id = appExportService.install(fileExport);
        fileExport.setId(id);


        //异步执行导出
        CompletableFuture.runAsync(() -> {
            String footer = null;
            String header = null;
            if (pdfConfig.containsKey(deptId.toString())) {
                JSONObject config = pdfConfig.getJSONObject(deptId.toString());
                footer = config.getString("footer");
                header = config.getString("header");
            }
            String deptName = sysDeptService.getDeptName(deptId);
            logger.info("安全问题导出,生成pdf文件开始.....");
            List<InputStream> iss = new ArrayList<>(safetyIds.size());
            for (Integer safefyId : safetyIds) {
                logger.info("安全问题导出,deptName:{},safefyId:{}", deptName, safefyId);
                SafetyCheckDescDTO descDTO = desc(safefyId);
                JSONObject exportJson = getExportJson(descDTO);
                exportJson.put("deptName", deptName);
                ClassPathResource resource = new ClassPathResource(HTML_TEMPLATE_PATH);
                String html;
                try {
                    InputStream templateFileInputStream = resource.getInputStream();
                    File tempFile = FileUtil.copyTemplateFile(templateFileInputStream);
                    html = HtmlUtil.freeMarkerRender(exportJson, tempFile);
                    ByteArrayOutputStream arrayOutputStream = ItextPdfUtil.htmlToPdf(html, header, footer);
                    iss.add(new ByteArrayInputStream(arrayOutputStream.toByteArray()));
                } catch (Exception ex) {
                    logger.error("质量pdf导出异常", ex);
                }
            }
            logger.info("安全问题导出,生成pdf文件结束.....");
            InputStream is = null;
            if (suffix.equals("zip")) {
                try {
                    is = ZipUtil.zipPdfFile(iss);
                    logger.info("安全问题导出,生成zip压缩包成功.....");
                } catch (IOException e) {
                    logger.error("压缩文件失败", e);
                }
            } else {
                is = iss.get(0);
            }

            logger.info("安全问题导出,文件上传.....");
            String path = msFilePathConfig.getFilePath("safety/export", fileName, suffix);
            String upload = fileHandler.upload(path, is, FileExpirationRules.DAYS_7);

            logger.info("安全问题导出,更新导出记录.....");
            AppFileExportParam upFileExport = fileExport;
            upFileExport.setFileUrl(upload);
            upFileExport.setFileState(1);
            appExportService.update(upFileExport);
        });
    }

    @Override
    public SafetyCheckScreenDTO safetyCheckScreenStatistical(Integer deptId, Date startTime, Date endTime) throws BizException {
        logger.info("检查统计,deptId:{},startTime:{},endTime:{}", deptId, startTime, endTime);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        SafetyCheckScreenDTO data = safetyCheckMapper.selectStatisticalByDeptId(deptId, startTime, endTime);
        data.setCheckNum(0);
        return data;
    }

    @Override
    public SafetyCheckScreenDTO safetyCheckTypeAnalysis(Integer deptId, Date startTime, Date endTime) throws BizException {
        logger.info("上报问题类别分析,deptId:{},startTime:{},endTime:{}", deptId, startTime, endTime);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        SafetyCheckScreenDTO data = new SafetyCheckScreenDTO();
        List<SafetyIssueNumDTO> list = safetyCheckMapper.selectIssueTypeIdNum(deptId, startTime, endTime);
        if (!list.isEmpty()) {
            Integer allNum = list.stream().mapToInt(SafetyIssueNumDTO::getNum).sum();
            data.setQuestionNum(allNum);
            list.forEach(safetyIssueNumDTO -> {
                SafetyIssueType safetyIssueType = safetyIssueTypeMapper.selectByIssueTypeId(safetyIssueNumDTO.getIssueTypeId());
                if(null == safetyIssueType){
                    safetyIssueNumDTO.setIssueName("其他");
                }else{
                    safetyIssueNumDTO.setIssueName(safetyIssueType.getName());
                }
                Double percent = MathUtil.divide(safetyIssueNumDTO.getNum(), allNum, 4) * 100;
                safetyIssueNumDTO.setPercent(percent);
            });
        }
        data.setList(list);
        return data;
    }

    @Override
    public SafetyCheckUnfinishedDTO safetyCheckUnfinished(Integer deptId, Date startTime, Date endTime) throws BizException {
        logger.info("未销问题分析,deptId:{},startTime:{},endTime:{}", deptId, startTime, endTime);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        SafetyCheckUnfinishedDTO data = safetyCheckMapper.selectUnfinishedByDeptId(deptId, startTime, endTime);
        Integer num = data.getAllNum();
        data.setGeneralIssuesPercent(0D);
        data.setUrgencyIssuesPercent(0D);
        data.setExceedPercent(0D);
        if (num != 0) {
            Double generalIssuesPercent = MathUtil.divide(data.getGeneralIssues(), num, 4) * 100;
            Double urgencyIssuesPercent = MathUtil.divide(data.getUrgencyIssues(), num, 4) * 100;
            Double exceedPercent = MathUtil.divide(data.getExceed(), num, 4) * 100;
            data.setGeneralIssuesPercent(MathUtil.round(generalIssuesPercent, 2));
            data.setUrgencyIssuesPercent(MathUtil.round(urgencyIssuesPercent, 2));
            data.setExceedPercent(MathUtil.round(exceedPercent, 2));
        }
        return data;
    }

    @Override
    public List<SafetyCheckPartStatisticalDTO> safetyCheckPartAnalysis(Integer deptId, Date startTime, Date endTime) throws BizException {
        logger.info("上报问题部位分析,deptId:{},startTime:{},endTime:{}", deptId, startTime, endTime);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        return safetyCheckMapper.selectPartByCheckTime(deptId, null,startTime, endTime);
    }

    private JSONObject getExportJson(SafetyCheckDescDTO descDTO) {
        JSONObject exportJson = JSONObject.parseObject(JSONObject.toJSONString(descDTO));
        setExportJsonParam(exportJson);
        String imgUrlString = setExportJsonImg(exportJson);
        exportJson.put("imgUrlList", imgUrlString);
        return exportJson;
    }

    private void setExportJsonParam(JSONObject json) {
        Integer state = json.getInteger("state");
        JSONArray logIndex = new JSONArray();
        JSONArray logList = json.getJSONArray("logList");
        JSONArray logJson = new JSONArray();
        logList.forEach(o -> {
            JSONObject log = (JSONObject) o;
            Integer opType = log.getInteger("opType");
            String opTime = DateUtil.formatDate(log.getDate("opTime"), DateUtil.DATE_TIME_FORMAT);
            log.put("opTime", opTime);
            String imgUrlList = setExportJsonImg(log);
            log.put("imgUrlList", imgUrlList);
            if (SafetyCheckUserType.RECTIFIER.getValue().equals(opType) && json.containsKey("rectifyRequire")) {
                log.put("opTime", DateUtil.formatDate(json.getDate("rectifyTime"), DateUtil.DATE_FORMAT));
                log.put("rectifyRequire", json.getString("rectifyRequire"));
                log.put("opDesc", "已完成：已经按要求整改完成," + log.get("opDesc"));
            } else {
                Integer opResult = log.getInteger("opResult");
                if (SafetyOptionResult.QUALIFIED.getValue().equals(opResult)) {
                    log.put("opDesc", "合格：" + log.get("opDesc"));
                }
            }
            if (!SafetyCheckUserType.REPORTER.getValue().equals(opType)) {
                logIndex.add(opType);
                logJson.add(log);
            } else {
                json.put("checkTime", log.getString("opTime"));
            }
        });
        Integer[] process = SafetyCheckState.process(state);
        if (process != null) {
            List<Integer> processList = Arrays.asList(process);
            logIndex.addAll(processList);
            JSONArray userList = json.getJSONArray("userList");
            userList.forEach(o -> {
                JSONObject user = (JSONObject) o;
                JSONObject log = new JSONObject();
                if (processList.contains(user.getInteger("type"))) {
                    log.put("opDesc", "未完成");
                    log.put("opType", user.getInteger("type"));
                    log.put("userName", user.getString("userName"));
                    logJson.add(log);
                }
            });
        }
        json.put("logList", logJson);
        json.put("logIndex", logIndex);
    }

    private String setExportJsonImg(JSONObject json) {
        if (json.containsKey("imgUrlList")) {
            JSONArray imgUrlList = json.getJSONArray("imgUrlList");
            StringBuffer imgUrlString = new StringBuffer();
            imgUrlList.forEach(o -> {
                String imgUrl = String.valueOf(o);
                imgUrlString.append(String.format(EXPORT_IMG_TEMPLATE, imgUrl));
            });
            return imgUrlString.toString();
        }
        return null;
    }


    /**
     * 生成消息
     *
     * @param qualityCheckLogParam 操作日志
     * @param check                问题对象
     * @param opTime               操作时间
     * @return
     */
    private void generateMessage(SafetyCheckLogParam qualityCheckLogParam, SafetyCheck check, Date opTime) {
        Integer state = check.getState();
        if (SafetyCheckState.SUCCESS.getValue().equals(state)) {
            //如果状态为已完成，就直接返回
            return;
        }
        Integer checkId = check.getId();
        SafetyMsgDTO qualityMsgDTO = new SafetyMsgDTO();
        qualityMsgDTO.setCheckId(checkId);
        qualityMsgDTO.setDeptId(check.getDeptId());
        qualityMsgDTO.setTime(opTime);
        String title = "";
        String content = "";
        List<SafetyCheckUserDTO> list = new ArrayList<>();
        String time = DateUtil.formatDate(opTime, "yyyy-MM-dd HH:mm");
        if (SafetyCheckState.UNQUALIFIED_REVIEW.getValue().equals(state)) {
            title = SafetyMsgTemplate.UNQUALIFIED_REVIEW.getTitle();
            content = String.format(SafetyMsgTemplate.UNQUALIFIED_REVIEW.getContent(), qualityCheckLogParam.getOpUserName(), time);
            list = safetyCheckUserMapper.selectQualityCheckUserDTOList(checkId, SafetyOptionType.RECTIFY.getValue());
        } else if (SafetyCheckState.UNQUALIFIED_VERIFY.getValue().equals(state)) {
            title = SafetyMsgTemplate.UNQUALIFIED_VERIFY.getTitle();
            content = String.format(SafetyMsgTemplate.UNQUALIFIED_VERIFY.getContent(), qualityCheckLogParam.getOpUserName(), time);
            list = safetyCheckUserMapper.selectQualityCheckUserDTOList(checkId, SafetyOptionType.RECTIFY.getValue());
        } else if (SafetyCheckState.TO_BE_REVIEWED.getValue().equals(state)) {
            title = SafetyMsgTemplate.TO_BE_REVIEWED.getTitle();
            //获取上报人
            SafetyCheckLog qualityCheckLog = safetyCheckLogMapper.selectByCheckIdAndOpType(checkId, SafetyOptionType.REPORT.getValue());
            content = String.format(SafetyMsgTemplate.TO_BE_REVIEWED.getContent(), qualityCheckLogParam.getOpUserName(), time, qualityCheckLog.getOpUserName());
            list = safetyCheckUserMapper.selectQualityCheckUserDTOList(checkId, SafetyOptionType.REVIEW.getValue());
        } else if (SafetyCheckState.TO_BE_VERIFIED.getValue().equals(state)) {
            title = SafetyMsgTemplate.TO_BE_VERIFIED.getTitle();
            //获取整改人
            SafetyCheckLog qualityCheckLog = safetyCheckLogMapper.selectByCheckIdAndOpType(checkId, SafetyOptionType.RECTIFY.getValue());
            content = String.format(SafetyMsgTemplate.TO_BE_VERIFIED.getContent(), qualityCheckLogParam.getOpUserName(), time, qualityCheckLog.getOpUserName());
            list = safetyCheckUserMapper.selectQualityCheckUserDTOList(checkId, SafetyOptionType.VERIFY.getValue());
        }
        List<Integer> msgChannelList = new ArrayList<>();
        msgChannelList.add(AppWarnMsgChannel.WXMP.value());
        msgChannelList.add(AppWarnMsgChannel.MS.value());

        List<AppMsgToUserDTO> appMsgToUserDTOS = new ArrayList<>();
        for (SafetyCheckUserDTO qualityCheckUserDTO : list) {
            AppMsgToUserDTO toUserDTO = new AppMsgToUserDTO();
            toUserDTO.setUserId(qualityCheckUserDTO.getUserId());
            toUserDTO.setNickName(qualityCheckUserDTO.getUserName());
            toUserDTO.setPhone(qualityCheckUserDTO.getUserPhone());
            appMsgToUserDTOS.add(toUserDTO);
        }

        PushMsgDTO pushMsgDTO = new PushMsgDTO();
        pushMsgDTO.setDeptId(check.getDeptId());
        pushMsgDTO.setTitle(title);
        pushMsgDTO.setContent(content);
        pushMsgDTO.setModuleType(AppWarnModuleType.SAFETY.value());
        pushMsgDTO.setMsgObjectId(String.valueOf(checkId));
        pushMsgDTO.setMsgChannelList(msgChannelList);
        pushMsgDTO.setToUserList(appMsgToUserDTOS);
        pushMsgDTO.setTime(opTime);
        amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(pushMsgDTO));
    }

    /**
     * 发送报警消息
     *
     * @param qualityCheckDTO
     * @param checkUsers
     */
    private void generateMessage(SafetyCheckDTO qualityCheckDTO, List<SafetyCheckUserParam> checkUsers) {
        Integer checkId = qualityCheckDTO.getCheckId();
        Integer deptId = qualityCheckDTO.getDeptId();
        Date checkTime = qualityCheckDTO.getCheckTime();
        String checkUserName = qualityCheckDTO.getCheckUserName();
        //接收消息人员
        //整改人列表
        List<AppMsgToUserDTO> rectifyUserList = new ArrayList<>();
        //抄送人列表
        List<AppMsgToUserDTO> ccUserList = new ArrayList<>();
        for (SafetyCheckUserParam checkUser : checkUsers) {
            AppMsgToUserDTO toUserDTO = new AppMsgToUserDTO();
            toUserDTO.setUserId(checkUser.getUserId());
            toUserDTO.setNickName(checkUser.getUserName());
            toUserDTO.setPhone(checkUser.getUserPhone());
            if (SafetyCheckUserType.REPORTER.getValue().equals(checkUser.getType())) {
                checkUserName = checkUser.getUserName();
            }
            if (SafetyCheckUserType.RECTIFIER.getValue().equals(checkUser.getType())) {
                rectifyUserList.add(toUserDTO);
            }
            if (SafetyCheckUserType.CC.getValue().equals(checkUser.getType())) {
                ccUserList.add(toUserDTO);
            }
        }
        //接收通道
        List<Integer> msgChannelList = new ArrayList<>();
        msgChannelList.add(AppWarnMsgChannel.WXMP.value());
        msgChannelList.add(AppWarnMsgChannel.MS.value());
        //检查时间
        String time = DateUtil.formatDate(checkTime, "yyyy-MM-dd HH:mm");
        //发送消息给整改人
        String rectifyTitle = SafetyMsgTemplate.RECTIFIED.getTitle();
        String rectifyContent = String.format(SafetyMsgTemplate.RECTIFIED.getContent(), checkUserName, time);

        PushMsgDTO pushMsgDTO = new PushMsgDTO();
        pushMsgDTO.setDeptId(deptId);
        pushMsgDTO.setTitle(rectifyTitle);
        pushMsgDTO.setContent(rectifyContent);
        pushMsgDTO.setModuleType(AppWarnModuleType.SAFETY.value());
        pushMsgDTO.setMsgObjectId(String.valueOf(checkId));
        pushMsgDTO.setMsgChannelList(msgChannelList);
        pushMsgDTO.setToUserList(rectifyUserList);
        pushMsgDTO.setTime(checkTime);
        //发送消息给抄送人
        String ccTitle = SafetyMsgTemplate.SUCCESS.getTitle();
        String ccContent = String.format(SafetyMsgTemplate.SUCCESS.getContent(), checkUserName, time);

        PushMsgDTO ccPushMsgDTO = new PushMsgDTO();
        ccPushMsgDTO.setDeptId(deptId);
        ccPushMsgDTO.setTitle(ccTitle);
        ccPushMsgDTO.setContent(ccContent);
        ccPushMsgDTO.setModuleType(AppWarnModuleType.SAFETY.value());
        ccPushMsgDTO.setMsgObjectId(String.valueOf(checkId));
        ccPushMsgDTO.setMsgChannelList(msgChannelList);
        ccPushMsgDTO.setToUserList(ccUserList);
        ccPushMsgDTO.setTime(checkTime);
        try {
            amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(pushMsgDTO));
            amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(ccPushMsgDTO));
        } catch (Exception ex) {
            logger.error("", ex);
        }

    }

    /**
     * 查询问题列表分页
     *
     * @param list                 列表数据
     * @param safetyCheckListParam 列表请求查询数据
     * @param safetyCheckListDTO   列表返回数据
     * @return
     * @author hw
     * @date 2020/8/7 14:58
     **/
    private void calculatePage(List<SafetyCheckDTO> list, SafetyCheckListParam safetyCheckListParam, SafetyCheckListDTO safetyCheckListDTO) {
        if (safetyCheckListParam.getPageSize() != null && safetyCheckListParam.getPageNum() != null) {
            int pages = (list.size() + safetyCheckListParam.getPageSize() - 1) / safetyCheckListParam.getPageSize();
            int subListStart = safetyCheckListParam.getPageNum().equals(1) ? 0 : ((safetyCheckListParam.getPageNum() - 1) * safetyCheckListParam.getPageSize());
            int subListEnd = subListStart + safetyCheckListParam.getPageSize();
            safetyCheckListDTO.setTotal(list.size());
            safetyCheckListDTO.setPages(pages);
            if (list.size() < subListStart) {
                safetyCheckListDTO.setCheckList(new ArrayList<>());
                return;
            }
            safetyCheckListDTO.setCheckList(list.subList(subListStart, subListEnd <= list.size() ? subListEnd : list.size()));
        }
    }

    /**
     * 筛选问题上报列表
     *
     * @param safetyCheckListParam 问题上报请求类
     * @param list                 问题上报数据
     * @param safetyCheckListDTO   问题上报返回类
     * @return
     * @author hw
     * @date 2020/8/7 11:35
     **/
    private SafetyCheckListDTO screeningCheckList(SafetyCheckListParam safetyCheckListParam, List<SafetyCheckDTO> list, SafetyCheckListDTO safetyCheckListDTO, Boolean type) {
        List<SafetyCheckDTO> newList = new ArrayList<>();
        for (SafetyCheckDTO checkDTO : list) {
            if (SafetyCheckState.TO_BE_RECTIFIED.getValue().equals(checkDTO.getState()) && SafetyCheckUserType.RECTIFIER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
            } else if (SafetyCheckState.UNQUALIFIED_VERIFY.getValue().equals(checkDTO.getState()) && SafetyCheckUserType.RECTIFIER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
            } else if (SafetyCheckState.UNQUALIFIED_REVIEW.getValue().equals(checkDTO.getState()) && SafetyCheckUserType.RECTIFIER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
            } else if (SafetyCheckState.TO_BE_REVIEWED.getValue().equals(checkDTO.getState()) && SafetyCheckUserType.REVIEWER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
            } else if (SafetyCheckState.TO_BE_VERIFIED.getValue().equals(checkDTO.getState()) && SafetyCheckUserType.VERIFIER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
            }
        }
        safetyCheckListDTO.setDisposeNum(newList.size());
        if (type) {
            calculatePage(newList, safetyCheckListParam, safetyCheckListDTO);
        } else {
            safetyCheckListDTO.setCheckList(newList);
        }
        return safetyCheckListDTO;
    }


    /**
     * @Author hw
     * @Description 保存问题上报主表
     * @Date 2020/8/5
     * @param: safetyCheckParam
     * @param: safetyCheck
     * @return: null
     **/
    private void insertCheck(SafetyCheckParam safetyCheckParam, SafetyCheck safetyCheck) {

        //计算整改需要的时间
        Date rectifyStartTime = new Date();
        LocalDate now = LocalDateTime.ofInstant(rectifyStartTime.toInstant(), ZoneId.systemDefault()).toLocalDate();
        LocalDate endTime = LocalDateTime.ofInstant(safetyCheckParam.getRectifyDuration().toInstant(), ZoneId.systemDefault()).toLocalDate();
        Long duration = endTime.toEpochDay() - now.toEpochDay();

        BeanUtils.copyProperties(safetyCheckParam, safetyCheck);


        safetyCheck.setRectifyDuration(duration.intValue());
        safetyCheck.setRectifyStartTime(rectifyStartTime);
        safetyCheck.setRectifyEndTime(safetyCheckParam.getRectifyDuration());
        safetyCheck.setCheckTime(rectifyStartTime);
        //新增问题上报是默认待整改
        safetyCheck.setState(SafetyCheckState.TO_BE_RECTIFIED.getValue());
        //新增问题上报默认为未超期
        safetyCheck.setOverdue(OverdueStatus.NOT_OVERDUE.getValue());

        safetyCheckMapper.insertSelective(safetyCheck);

    }

    /**
     * @param :safetyCheckParam
     * @param :safetyCheck
     * @Author hw
     * @Description 保存安全问题记录相关人员和安全问题流程处理
     * @Date 2020/8/5
     * @return: SafetyCheckLog
     **/
    private SafetyCheckLog inserCheckUserAndLog(SafetyCheckParam safetyCheckParam, SafetyCheck safetyCheck) {
        SafetyCheckLog checkLog = null;
        for (SafetyCheckUserParam userParam : safetyCheckParam.getCheckUsers()) {
            if (SafetyCheckUserType.parseValue(userParam.getType()) == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "人员类型编码不存在");
            }
            //判断对应人员是否为上报人如果是上报人需要在安全问题流程表添加数据
            if (SafetyCheckUserType.REPORTER.getValue().equals(userParam.getType())) {
                checkLog = new SafetyCheckLog();
                checkLog.setCheckId(safetyCheck.getId());
                checkLog.setOpType(SafetyCheckUserType.REPORTER.getValue());
                checkLog.setOpUserId(userParam.getUserId());
                checkLog.setOpUserName(userParam.getUserName());
                checkLog.setOpTime(new Date());
                safetyCheckLogMapper.insertSelective(checkLog);
            }
            //储存安全问题相关人员信息
            SafetyCheckUser checkUser = new SafetyCheckUser();
            checkUser.setCheckId(safetyCheck.getId());
            checkUser.setType(userParam.getType());
            checkUser.setUserId(userParam.getUserId());
            checkUser.setUserName(userParam.getUserName());
            checkUser.setUserPhone(userParam.getUserPhone());
            safetyCheckUserMapper.insertSelective(checkUser);
        }
        return checkLog;
    }

    /**
     * @Author hw
     * @Description 安全问题流程处理 前置校验
     * @Date 2020/8/5 9:53
     * @Param:
     * @Return:
     **/
    private void verifyCheckLog(SafetyCheckLogParam safetyCheckLogParam, SafetyCheck check) {
        if (check == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "没有查询到对应的安全问题");
        }
        SafetyCheckUser checkUser = safetyCheckUserMapper.selectByCheckIdAndUserIdAndType(check.getId(), safetyCheckLogParam.getOpUserId(), safetyCheckLogParam.getOpType());
        if (checkUser == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前用户无法做该操作");
        }
        if (SafetyOptionType.parseValue(safetyCheckLogParam.getOpType()) == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "操作类型错误");
        }
        if (!SafetyOptionType.REPORT.getValue().equals(safetyCheckLogParam.getOpType()) && !SafetyOptionType.RECTIFY.getValue().equals(safetyCheckLogParam.getOpType())) {
            if (safetyCheckLogParam.getOpResult() == null || SafetyOptionResult.parseValue(safetyCheckLogParam.getOpResult()) == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "操作结果错误");
            }
        }
        //当安全整改问题已经存在则无法上报
        if (SafetyOptionType.REPORT.getValue().equals(safetyCheckLogParam.getOpType())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前状态无法上报");
        }
        //当安全问题状态不为待整改、待整改(复查不合格)、待整改(核验不合格) 无法整改
        if (SafetyOptionType.RECTIFY.getValue().equals(safetyCheckLogParam.getOpType()) && !SafetyCheckState.UNQUALIFIED_REVIEW.getValue().equals(check.getState()) && !SafetyCheckState.UNQUALIFIED_VERIFY.getValue().equals(check.getState()) && !SafetyCheckState.TO_BE_RECTIFIED.getValue().equals(check.getState())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前状态无法整改");
        }
        //当安全问题状态不为待复查时无法复查
        if (SafetyOptionType.REVIEW.getValue().equals(safetyCheckLogParam.getOpType()) && !SafetyCheckState.TO_BE_REVIEWED.getValue().equals(check.getState())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前状态无法复查");
        }
        //当安全问题状态不为带核验时无法核验
        if (SafetyOptionType.VERIFY.getValue().equals(safetyCheckLogParam.getOpType()) && !SafetyCheckState.TO_BE_VERIFIED.getValue().equals(check.getState())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前状态无法核验");
        }
    }

    @Override
    public List<SafetyIssueNumDTO> safetyLogGroupByIssueId(Integer deptId) throws BizException {



        List<SafetyIssueNumDTO> issueList = safetyCheckMapper.selectIssueNum(deptId, null, null);

        return issueList;
    }

    @Override
    public StatisticsProgressDTO getStatisticsProgressDTO(Integer deptId, Integer userId, String startTime, String endTime) {

        //我的上报
        CheckSearchParam csp = new CheckSearchParam();
        csp.setDeptId(deptId);
        csp.setUserId(userId);
        csp.setTypeList(Collections.singletonList(SafetyCheckUserType.REPORTER.getValue()));
        Integer reportCount = safetyCheckMapper.selectCount(csp);

        //我的核验
        csp.setTypeList(Collections.singletonList(SafetyCheckUserType.VERIFIER.getValue()));
        List<Integer> states = new ArrayList<>();
        states.add(SafetyCheckState.TO_BE_VERIFIED.getValue());
        states.add(SafetyCheckState.UNQUALIFIED_VERIFY.getValue());
        states.add(SafetyCheckState.SUCCESS.getValue());
        csp.setStateList(states);
        csp.setWaitFix(false);
        Integer checkCount = safetyCheckMapper.selectCount(csp);

        List<Integer> sceneList = Stream.of(SafetyCheckUserType.RECTIFIER.getValue(), SafetyCheckUserType.REVIEWER.getValue(), SafetyCheckUserType.VERIFIER.getValue()).collect(Collectors.toList());

        CheckSearchParam param = new CheckSearchParam();
        param.setDeptId(deptId);
        param.setUserId(userId);
        param.setStartTime(startTime);
        param.setEndTime(endTime);

        List<StatisticsProgressUnitDTO> taskProgressList = new ArrayList<>();
        for (Integer scene : sceneList) {

            param.setTypeList(Collections.singletonList(scene));

            if (SafetyCheckUserType.RECTIFIER.getValue().equals(scene)) {
                List<Integer> stateList = new ArrayList<>();
                stateList.add(SafetyCheckState.TO_BE_RECTIFIED.getValue());
                stateList.add(SafetyCheckState.UNQUALIFIED_REVIEW.getValue());
                stateList.add(SafetyCheckState.UNQUALIFIED_VERIFY.getValue());
                param.setStateList(stateList);
            } else if (SafetyCheckUserType.REVIEWER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(SafetyCheckState.TO_BE_REVIEWED.getValue()));
            } else if (SafetyCheckUserType.VERIFIER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(SafetyCheckState.TO_BE_VERIFIED.getValue()));
            }

            ////待处理数量
            Integer waitFixCount = safetyCheckMapper.selectCount(param);

            //待复查-待核验-完成
            if (SafetyCheckUserType.RECTIFIER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(SafetyCheckState.TO_BE_REVIEWED.getValue()));
            } else if (SafetyCheckUserType.REVIEWER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(SafetyCheckState.TO_BE_VERIFIED.getValue()));
            } else if (SafetyCheckUserType.VERIFIER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(SafetyCheckState.SUCCESS.getValue()));
            }
            //已处理数量
            Integer completeCount = safetyCheckMapper.selectCount(param);

            StatisticsProgressUnitDTO v = new StatisticsProgressUnitDTO();
            v.setScene(scene);
            v.setTotal(waitFixCount + completeCount);
            v.setCompleteCount(completeCount);
            taskProgressList.add(v);
        }
        StatisticsProgressDTO res = new StatisticsProgressDTO();
        res.setReportCount(reportCount);
        res.setCheckCount(checkCount);
        res.setTaskProgressList(taskProgressList);
        return res;
    }

    @Override
    public CheckStatisticsDTO getCheckStatistics(CheckSearchParam param) {

        param.setWaitFix(false);
        //总数
        Integer totalCount = safetyCheckMapper.selectCount(param);

        //上报总数
        param.setTypeList(Collections.singletonList(SafetyCheckUserType.REPORTER.getValue()));
        Integer reportTotalCount = safetyCheckMapper.selectCount(param);

        //复查不合格
        param.setTypeList(Collections.singletonList(SafetyCheckUserType.REVIEWER.getValue()));
        param.setStateList(Collections.singletonList(SafetyCheckState.UNQUALIFIED_REVIEW.getValue()));
        Integer reviewNoPassCount = safetyCheckMapper.selectCount(param);

        //核验不合格
        param.setTypeList(Collections.singletonList(SafetyCheckUserType.VERIFIER.getValue()));
        param.setStateList(Collections.singletonList(SafetyCheckState.UNQUALIFIED_VERIFY.getValue()));
        Integer verifiedNoPassCount = safetyCheckMapper.selectCount(param);

        //合格
        param.setStateList(Collections.singletonList(SafetyCheckState.SUCCESS.getValue()));
        Integer passCount = safetyCheckMapper.selectCount(param);

        param.setWaitFix(true);
        //待整改
        param.setTypeList(Collections.singletonList(SafetyCheckUserType.RECTIFIER.getValue()));
        param.setStateList(Collections.singletonList(SafetyCheckState.TO_BE_RECTIFIED.getValue()));
        Integer fixCount = safetyCheckMapper.selectCount(param);

        //待复查
        param.setTypeList(Collections.singletonList(SafetyCheckUserType.REVIEWER.getValue()));
        param.setStateList(Collections.singletonList(SafetyCheckState.TO_BE_REVIEWED.getValue()));
        Integer reviewCount = safetyCheckMapper.selectCount(param);

        //待核验
        param.setTypeList(Collections.singletonList(SafetyCheckUserType.VERIFIER.getValue()));
        param.setStateList(Collections.singletonList(SafetyCheckState.TO_BE_VERIFIED.getValue()));
        Integer verifiedCount = safetyCheckMapper.selectCount(param);

        CheckStatisticsDTO res = new CheckStatisticsDTO();
        res.setTotalCount(totalCount);
        res.setQuestionCount(totalCount);
        res.setCheckCount(0);
        res.setFixCount(fixCount + reviewNoPassCount + verifiedNoPassCount);
        res.setReviewNoPassCount(reviewNoPassCount);
        res.setVerifiedNoPassCount(verifiedNoPassCount);
        res.setNoPassCount(reviewNoPassCount + verifiedNoPassCount);
        res.setReviewCount(reviewCount);
        res.setVerifiedCount(verifiedCount);
        res.setPassCount(passCount);
        res.setReportTotalCount(reportTotalCount);
        res.setVerifiedTotalCount(verifiedCount + verifiedNoPassCount + passCount);
        return res;
    }

    @Override
    public PageVO<CheckDetailDTO> getCheckPage(CheckSearchParam param) {
        PageVOUtil.startPage(param);
        List<CheckDetailDTO> list = safetyCheckMapper.selectCheckDetailDTOList(param);
        for (CheckDetailDTO v : list) {
            v.setImgUrlList(safetyCheckImgMapper.selectByCheckId(v.getCheckId(), SafetyCheckUserType.REPORTER.getValue(), null));
            v.setRectifyImgUrlList(safetyCheckImgMapper.selectByCheckId(v.getCheckId(), SafetyCheckUserType.RECTIFIER.getValue(), null));
            v.setRectifyUserName(safetyCheckUserMapper.selectUserNamesByType(v.getCheckId(), SafetyCheckUserType.RECTIFIER.getValue()));
        }
        PageVOUtil.clearPage();
        return PageVOUtil.page(PageInfo.of(list));
    }

    @Override
    public void deleteBatch(List<Integer> idList) {
        if(CollectionUtils.isEmpty(idList)){
            return;
        }
        safetyCheckMapper.deleteBatch(idList);
    }

}
